package no.ntnu.fp.su;

import no.ntnu.fp.su.util.GaussianRandomWalk;
/**
 * A model of the evolution of well flow. Some parameters have been tuned to give interesting data unrealistically
 * fast, to make it easy to test all aspects of the WATCH system being implemented.
 *
 * The temperature of petroleum in the reservoir is assumed to be around 150 degrees Celsius, based on [0].
 * 
 * The density of petroleum is assumed to be 800kg/m^3, from [1].
 * 
 * [0] Andrew Clennel Palmer, Roger A. King. Subsea pipeline engineering. http://books.google.no/books?id=gYVOFx_jS1gC&lpg=PT288&ots=LvhORD_Uve&pg=PT288#v=onepage&q=&f=false
 * [1] England, Mackenzie, Mann & Quigley. The movement and entrapment of petroleum fluids in the subsurface. Journal of the Geological Society. 144 (1987): 327-47.
 */
public class Flow {
	public static final double meanTemperature = 150; // C
	public static final double minTemperature = 140; // C
	public static final double maxTemperature = 160; // C
	public static final double meanSandContent = 0.0; // %
	public static final double minSandContent = 0.0; // %
	public static final double maxSandContent = 1.0; // %
	public static final double meanPressure = 17236893/8.0; // pascal
	public static final double minPressure = meanPressure/4.0; // pascal
	public static final double maxPressure = meanPressure+(3/4.0)*meanPressure; // pascal
	public static final double petroleumDensity=800; // kg/m^3
	public static final double heatLossPerMeter=.001;
	public static final double pipeTemperature=60.0;
	private double temperature = meanTemperature;
	private double sandContent = meanSandContent;
	private double pressure = meanPressure;
	private GaussianRandomWalk temperatureProcess=new GaussianRandomWalk(meanTemperature, minTemperature, maxTemperature, 0.0, 0.1);
	private GaussianRandomWalk sandProcess=new GaussianRandomWalk(meanSandContent, minSandContent, maxSandContent, -0.02, 0.1);
	private GaussianRandomWalk pressureProcess=new GaussianRandomWalk(meanPressure, minPressure, maxPressure, 0, meanPressure/100.0);
	
	public double getTemperature(double metersFromReservoir) {
		return temperature-(temperature-pipeTemperature)*heatLossPerMeter*metersFromReservoir; // simplification
	}
	public double getSandContent() {
		return sandContent;
	}
	public double getPressure() {
		return pressure;
	}
	/**
	 * Flow velocity from pressure, petroleum density from [2]
	 */
	public double getVelocity() {
		return Math.sqrt(2.0*pressure/petroleumDensity);
	}
	public void tick() {
		temperature=temperatureProcess.next();
		sandContent=sandProcess.next();
		pressure=.05*pressureProcess.next()+.95*meanPressure*(temperature/meanTemperature);// Enough to make temperature and pressure correlated.
	}
}
